package com.sino.config.server;

import org.apache.log4j.Logger;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.util.Daos;
import org.nutz.lang.ContinueLoop;
import org.nutz.lang.Each;
import org.nutz.lang.ExitLoop;
import org.nutz.lang.Lang;
import org.nutz.lang.LoopException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.sino.config.server.ConfigServerApplication.Consts.InstalledPermission;
import com.sino.config.server.ConfigServerApplication.Consts.InstalledRole;
import com.sino.config.server.bean.acl.Permission;
import com.sino.config.server.bean.acl.Role;
import com.sino.config.server.bean.acl.RolePermission;
import com.sino.config.server.bean.acl.User;
import com.sino.config.server.bean.acl.User.Status;
import com.sino.config.server.bean.acl.UserRole;
import com.sino.config.server.ext.matcher.SINOCredentialsMatcher;
import com.sino.config.server.service.acl.PermissionService;
import com.sino.config.server.service.acl.RolePermissionService;
import com.sino.config.server.service.acl.RoleService;
import com.sino.config.server.service.acl.UserRoleService;
import com.sino.config.server.service.acl.UserService;

/**
 * @author kerbores
 *
 */
@SpringBootApplication
@EnableRedisHttpSession
public class ConfigServerApplication extends WebMvcConfigurerAdapter {

	/**
	 * 常量
	 * 
	 * @author kerbores
	 *
	 */
	public static class Consts {

		/**
		 * 内置角色
		 * 
		 * @author kerbores
		 *
		 */
		public static enum InstalledRole {
			SU("su", "超级管理员"),
			/**
			 * 
			 */
			MANAGER("manager", "项目管理员"),
			/**
			 * 
			 */
			USER("user", " 普通用户"),
			;
			private String name;

			private String description;

			public Role toRole() {
				Role role = new Role();
				role.setName(name);
				role.setDescription(description);
				return role;
			}

			/**
			 * @param name
			 * @param description
			 */
			private InstalledRole(String name, String description) {
				this.name = name;
				this.description = description;
			}

			/**
			 * @return the name
			 */
			public String getName() {
				return name;
			}

			/**
			 * @param name
			 *            the name to set
			 */
			public void setName(String name) {
				this.name = name;
			}

			/**
			 * @return the description
			 */
			public String getDescription() {
				return description;
			}

			/**
			 * @param description
			 *            the description to set
			 */
			public void setDescription(String description) {
				this.description = description;
			}

		}

		/**
		 * 内置权限
		 * 
		 * @author kerbores
		 *
		 */
		public static enum InstalledPermission {
			/**
			 * ++++++++++++++++++++++访问控制++++++++++++++++++++++++++++++++
			 */

			/**
			 * 用户管理
			 */
			USER_LIST("user.list", "用户管理"),
			/**
			 * 
			 */
			USER_ADD("user.add", "用户添加"),
			/**
			 * 
			 */
			USER_DETAIL("user.detail", "用户详情"),
			/**
			 * 
			 */
			USER_ROLE("user.role", "用户设置角色"),
			/**
			 * 
			 */
			USER_GRANT("user.grant", "用户设置权限"),
			/**
			 * 
			 */
			USER_EDIT("user.edit", "用户编辑"),
			/**
			 * 
			 */
			USER_DELETE("user.delete", "用户删除"),
			/**
			 * 角色管理
			 */
			ROLE_LIST("role.list", "角色管理"),
			/**
			 * 
			 */
			ROLE_ADD("role.add", "角色添加"),
			/**
			 * 
			 */
			ROLE_GRANT("role.grant", "角色设置权限"),
			/**
			 * 
			 */
			ROLE_EDIT("role.edit", "角色编辑"),
			/**
			 * 
			 */
			ROLE_DELETE("role.delete", "角色删除"),
			/**
			 * 权限管理
			 */
			PERMISSION_LIST("permission.list", "权限管理"),
			/**
			 * 权限添加
			 */
			PERMISSION_ADD("permission.add", "权限添加"),
			/**
			 * 权限编辑
			 */
			PERMISSION_EDIT("permission.edit", "编辑权限"),
			/**
			 * 权限删除
			 */
			PERMISSION_DELETE("permission.delete", "删除权限"),
			/**
			 * ++++++++++++++++++++++访问控制++++++++++++++++++++++++++++++++
			 */

			PROFILE_LIST("prifile.list", "Profile列表"),

			PROFILE_ADD("prifile.add", "Profile新增"),

			PROFILE_EDIT("prifile.edit", "Profile编辑"),

			PROFILE_DELETE("prifile.delete", "Profile删除"),

			LABEL_LIST("label.list", "Label列表"),

			LABEL_ADD("label.add", "Label新增"),

			LABEL_EDIT("label.edit", "Label编辑"),

			LABEL_DELETE("label.delete", "Label删除"),

			APPLICATION_LIST("application.list", "项目列表"),

			APPLICATION_ADD("application.add", "项目新增"),

			APPLICATION_EDIT("application.edit", "项目编辑"),

			APPLICATION_DELETE("application.delete", "项目删除"),

			;

			private String name;

			private String description;

			public Permission toPermission() {
				Permission permission = new Permission();
				permission.setName(name);
				permission.setDescription(description);
				return permission;
			}

			/**
			 * @param name
			 * @param description
			 */
			private InstalledPermission(String name, String description) {
				this.name = name;
				this.description = description;
			}

			/**
			 * @return the name
			 */
			public String getName() {
				return name;
			}

			/**
			 * @param name
			 *            the name to set
			 */
			public void setName(String name) {
				this.name = name;
			}

			/**
			 * @return the description
			 */
			public String getDescription() {
				return description;
			}

			/**
			 * @param description
			 *            the description to set
			 */
			public void setDescription(String description) {
				this.description = description;
			}

		}

		public static final String USER_KEY = "CONFIG-SERVER-USER";

	}

	public static void main(String[] args) throws Exception {
		SpringApplication application = new SpringApplication(ConfigServerApplication.class);
		application.addListeners(new ApplicationListener<ContextRefreshedEvent>() {
			Logger log = Logger.getLogger(getClass());

			Role admin;

			@Override
			public void onApplicationEvent(ContextRefreshedEvent event) {
				// 这里的逻辑将在应用启动之后执行
				ApplicationContext context = event.getApplicationContext();
				Dao dao = context.getBean(Dao.class);
				if (context.getParent() == null) {
					log.debug("application starter...");
					Daos.createTablesInPackage(dao, "com.sino.scaffold.bean", false);// 确保表结构正确
					Daos.migration(dao, "com.sino.scaffold.bean", true, true);
					initAcl(context);
				}
			}

			private void initAcl(ApplicationContext context) {
				log.debug("init acl...");
				final UserService userService = context.getBean(UserService.class);
				final RoleService roleService = context.getBean(RoleService.class);
				final PermissionService permissionService = context.getBean(PermissionService.class);
				final UserRoleService userRoleService = context.getBean(UserRoleService.class);
				final RolePermissionService rolePermissionService = context.getBean(RolePermissionService.class);

				Lang.each(InstalledRole.values(), new Each<InstalledRole>() {// 内置角色

					@Override
					public void invoke(int index, InstalledRole role, int length) throws ExitLoop, ContinueLoop, LoopException {
						if (roleService.fetch(Cnd.where("name", "=", role.getName())) == null) {
							Role temp = new Role();
							temp.setName(role.getName());
							temp.setDescription(role.getDescription());
							roleService.save(temp);
						}
					}
				});

				admin = roleService.fetch(Cnd.where("name", "=", InstalledRole.SU.getName()));

				if (admin == null) {// 这里理论上是进不来的,防止万一吧
					admin = new Role();
					admin.setName(InstalledRole.SU.getName());
					admin.setDescription(InstalledRole.SU.getDescription());
					admin = roleService.save(admin);
				}

				Lang.each(InstalledPermission.values(), new Each<InstalledPermission>() {// 内置权限

					@Override
					public void invoke(int index, InstalledPermission permission, int length) throws ExitLoop, ContinueLoop, LoopException {
						Permission temp = null;
						if ((temp = permissionService.fetch(Cnd.where("name", "=", permission.getName()))) == null) {
							temp = new Permission();
							temp.setName(permission.getName());
							temp.setDescription(permission.getDescription());
							temp = permissionService.save(temp);
						}

						// 给SU授权
						if (rolePermissionService.fetch(Cnd.where("permissionId", "=", temp.getId()).and("roleId", "=", admin.getId())) == null) {
							RolePermission rp = new RolePermission();
							rp.setRoleId(admin.getId());
							rp.setPermissionId(temp.getId());
							rolePermissionService.save(rp);
						}
					}
				});

				User surperMan = null;
				if ((surperMan = userService.fetch(Cnd.where("name", "=", "admin"))) == null) {
					surperMan = new User();
					surperMan.setName("admin");
					surperMan.setPassword(SINOCredentialsMatcher.password("admin", "123456"));
					surperMan.setStatus(Status.ENABLED);
					surperMan = userService.save(surperMan);
				}

				UserRole ur = null;
				if ((ur = userRoleService.fetch(Cnd.where("userId", "=", surperMan.getId()).and("roleId", "=", admin.getId()))) == null) {
					ur = new UserRole();
					ur.setUserId(surperMan.getId());
					ur.setRoleId(admin.getId());
					userRoleService.save(ur);
				}
			}

		});
		application.run(args);
	}

}
